home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / X11R4 / cmds / X / os / sprite / RCS / osfonts.c,v < prev    next >
Encoding:
Text File  |  1990-02-15  |  22.1 KB  |  998 lines

  1. head     1.1;
  2. branch   ;
  3. access   ;
  4. symbols  ;
  5. locks    ; strict;
  6. comment  @ * @;
  7.  
  8.  
  9. 1.1
  10. date     90.02.14.19.25.23;  author tve;  state Exp;
  11. branches ;
  12. next     ;
  13.  
  14.  
  15. desc
  16. @Original X11R4 distribution
  17. @
  18.  
  19.  
  20.  
  21. 1.1
  22. log
  23. @Initial revision
  24. @
  25. text
  26. @/************************************************************************
  27. Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
  28. and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
  29.  
  30.                         All Rights Reserved
  31.  
  32. Permission to use, copy, modify, and distribute this software and its 
  33. documentation for any purpose and without fee is hereby granted, 
  34. provided that the above copyright notice appear in all copies and that
  35. both that copyright notice and this permission notice appear in 
  36. supporting documentation, and that the names of Digital or MIT not be
  37. used in advertising or publicity pertaining to distribution of the
  38. software without specific, written prior permission.  
  39.  
  40. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  41. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  42. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  43. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  44. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  45. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  46. SOFTWARE.
  47.  
  48. ************************************************************************/
  49.  
  50. /* $XConsortium: osfonts.c,v 1.27 89/10/03 16:45:21 keith Exp $ */
  51.  
  52. #include <stdio.h>
  53. #include "Xos.h"
  54. #include <sys/dir.h>
  55. #include <sys/param.h>
  56. #include <sys/stat.h>
  57. #include <errno.h>
  58.  
  59. #include "X.h"
  60. #include "Xmd.h"
  61. #include "Xproto.h"
  62. #include "dixfontstr.h"
  63. #include "fontstruct.h"
  64. #include "osstruct.h"
  65. #include "misc.h"
  66. #include "opaque.h"
  67. #include "dixstruct.h"
  68.  
  69. #include "fonttype.h"
  70. #include "fontdir.h"
  71.  
  72. extern int errno;
  73.  
  74. extern void CopyISOLatin1Lowered();
  75. extern Atom    MakeAtom();
  76. extern char *defaultFontPath;
  77.  
  78. static int    ReadFontAlias ();
  79. static FontFile    FindFontFile ();
  80. static int    ReadFontDir ();
  81.  
  82. FontPathPtr        GetFontPath ();
  83.  
  84. /* maintained for benefit of GetFontPath */
  85. static FontPathPtr searchList = (FontPathPtr)NULL;
  86.  
  87. void
  88. FreeFontRecord(pFP)
  89.     FontPathPtr pFP;
  90. {
  91.     int i;
  92.     for (i=0; i<pFP->npaths; i++) {
  93.         xfree(pFP->paths[i]);
  94.     }
  95.     xfree(pFP->paths);
  96.     xfree(pFP->length);
  97.     xfree(pFP->osPrivate);
  98.     xfree(pFP);
  99. }
  100.  
  101. static FontPathPtr
  102. MakeFontPathRecord(size)
  103.     unsigned    size;
  104. {
  105.     FontPathPtr fp;    
  106.  
  107.     fp = (FontPathPtr)xalloc(sizeof(FontPathRec));
  108.     if (fp) {
  109.     fp->npaths = 0;
  110.     fp->size = size;
  111.     fp->length = (int *)xalloc(size * sizeof(int));
  112.     fp->paths = (char **)xalloc(size * sizeof(char *));
  113.     fp->osPrivate = (pointer *)xalloc(size * sizeof(pointer));
  114.     if (!fp->length || !fp->paths || !fp->osPrivate) {
  115.         xfree(fp->length);
  116.         xfree(fp->paths);
  117.         xfree(fp->osPrivate);
  118.         xfree(fp);
  119.         fp = (FontPathPtr)NULL;
  120.     }
  121.     }
  122.     return fp;
  123. }
  124.  
  125. static int
  126. AddFontPathElement(path, element, length, fontDir)
  127.     FontPathPtr path;
  128.     char *element;
  129.     int  length;
  130.     Bool fontDir;
  131. {
  132.     int index = path->npaths;
  133.     FontTable table;
  134.     char *nelt;
  135.     int status;
  136.  
  137.     if (fontDir)
  138.     {
  139.     status = ReadFontDir(element, &table, path);
  140.     if (status != Success)
  141.         return status;
  142.     }
  143.     nelt = (char *)xalloc(length + 1);
  144.     if (!nelt)
  145.     return BadAlloc;
  146.     if (index >= path->size)
  147.     {
  148.     int size = path->size << 1;
  149.     int *nlength;
  150.     char **npaths;
  151.     pointer *npriv;
  152.  
  153.     nlength = (int *)xrealloc(path->length, size*sizeof(int));
  154.     npaths = (char **)xrealloc(path->paths, size*sizeof(char *));
  155.     npriv = (pointer *)xrealloc(path->osPrivate, size * sizeof(pointer));
  156.     if (nlength && npaths && npriv)
  157.     {
  158.         path->size = size;
  159.         path->length = nlength;
  160.         path->paths = npaths;
  161.         path->osPrivate = npriv;
  162.     }
  163.     else
  164.     {
  165.         xfree(nlength);
  166.         xfree(npaths);
  167.         xfree(npriv);
  168.         return BadAlloc;
  169.     }
  170.     }
  171.     path->length[index] = length;
  172.     path->paths[index] = nelt;
  173.     strncpy(nelt, element, length);
  174.     nelt[length] = '\0';
  175.     path->osPrivate[index] = (pointer)table;
  176.     path->npaths++;
  177.     return Success;
  178. }
  179.  
  180. static void
  181. FreeFontPath(path)
  182.     FontPathPtr path;
  183. {
  184.     int     i, j;
  185.     FontPtr font;
  186.     FontTable table;
  187.  
  188.     /* 
  189.      * First all the back pointers for the outstanding fonts must be smashed
  190.      * to NULL so that when the font is freed, the removal from the (now
  191.      * freed) previous table can be skipped.
  192.      */
  193.     if (path) {
  194.     for (i = 0; i < path->npaths; i++) {
  195.         table = (FontTable) path->osPrivate[i];
  196.         for (j = 0; j < table->file.used; j++) {
  197.         if ((font = (FontPtr) table->file.ff[j].private) != NullFont)
  198.             font->osPrivate = NULL;
  199.         }
  200.         FreeFontTable (table);
  201.     }
  202.     FreeFontRecord (path);
  203.     }
  204. }
  205.  
  206. /*
  207.  * Font paths are not smashed to lower case. (Note "/usr/lib/X11/fonts")
  208.  *
  209.  * Allow initial font path to have names separated by spaces tabs or commas
  210.  */
  211. int
  212. SetDefaultFontPath(name)
  213.     char *    name;
  214. {
  215.     register char *start, *end;
  216.     char dirName[MAXPATHLEN];
  217.     FontPathPtr path;
  218.     int status;
  219.  
  220.     path = MakeFontPathRecord(3);
  221.     if (!path)
  222.     return BadAlloc;
  223.     end = name;
  224.     for (;;) {
  225.     start = end;
  226.     while ((*start == ' ') || (*start == '\t') || (*start == ','))
  227.         start++;
  228.     if (*start == '\0')
  229.         break;
  230.     end = start;
  231.     while ((*end != ' ') && (*end != '\t') && (*end != ',') &&
  232.         (*end != '\0'))
  233.        end++;
  234.     strncpy(dirName, start, end - start);
  235.     dirName[end - start] = '\0';
  236.     if (dirName[strlen(dirName) - 1] != '/')
  237.         strcat(dirName, "/");
  238.     status = AddFontPathElement(path, dirName, strlen (dirName), True);
  239.     if (status != Success)
  240.     {
  241.         FreeFontPath(path);
  242.         return status;
  243.     }
  244.     }
  245.     FreeFontPath(searchList);
  246.     searchList = path;
  247.     return Success;
  248. }
  249.  
  250. int
  251. SetFontPath(client, npaths, countedStrings)
  252.     ClientPtr    client;
  253.     unsigned    npaths;
  254.     char *    countedStrings;
  255. {
  256.     int i;
  257.     unsigned char * bufPtr = (unsigned char *)countedStrings;
  258.     char dirName[MAXPATHLEN];
  259.     unsigned int n;
  260.     FontPathPtr path;
  261.     int status;
  262.  
  263.     if (npaths == 0)
  264.     return SetDefaultFontPath(defaultFontPath); /* this frees old paths */
  265.  
  266.     path = MakeFontPathRecord(npaths);
  267.     if (!path)
  268.     return BadAlloc;
  269.     for (i=0; i<npaths; i++) {
  270.     n = (unsigned int)(*bufPtr++);
  271.     strncpy(dirName, (char *) bufPtr, (int) n);
  272.     dirName[n] = '\0';
  273.     if (dirName[n - 1] != '/')
  274.         strcat(dirName, "/");
  275.     status = AddFontPathElement(path, dirName, strlen (dirName), True);
  276.     if (status != Success)
  277.     {
  278.         FreeFontPath(path);
  279.         client->errorValue = i;
  280.         return status;
  281.     }
  282.     bufPtr += n;
  283.     }
  284.     FreeFontPath(searchList);
  285.     searchList = path;
  286.     return Success;
  287. }
  288.  
  289. FontPathPtr
  290. GetFontPath()
  291. {
  292.     return(searchList);
  293. }
  294.  
  295. static int
  296. FindFileType(name)
  297.     char *name;
  298. {
  299.     register int i, j, k;
  300.     char *ext;
  301.  
  302.     k = strlen(name);
  303.     for (i = 0; fontFileReaders[i].extension; i++) {
  304.     ext = fontFileReaders[i].extension;
  305.     j = strlen(ext);
  306.     if ((k > j) && (strcmp(ext, name + k - j) == 0))
  307.         return i;
  308.     }
  309.     return -1;
  310. }
  311.  
  312. static int
  313. ReadFontDir(directory, ptable, path)
  314.     char    *directory;
  315.     FontTable    *ptable;
  316.     FontPathPtr path;
  317. {
  318.     char file_name[MAXPATHLEN];
  319.     char font_name[MAXPATHLEN];
  320.     char dir_file[MAXPATHLEN];
  321.     char BUF[BUFSIZ];
  322.     FILE *file;
  323.     int count, i, status;
  324.     FontTable matchTable;
  325.     FontTable table = NullTable;
  326.  
  327.     strcpy(dir_file, directory);
  328.     if (directory[strlen(directory) - 1] != '/')
  329.      strcat(dir_file, "/");
  330.     strcat(dir_file, FontDirFile);
  331.     file = fopen(dir_file, "r");
  332.     if (file)
  333.     {
  334.     setbuf (file, BUF);
  335.     count = fscanf(file, "%d\n", &i);
  336.     if ((count == EOF) || (count != 1)) {
  337.         fclose(file);
  338.         return BadValue;
  339.     }
  340.     table = MakeFontTable(directory, count+10);
  341.     for (;;) {
  342.         count = fscanf(file, "%s %[^\n]\n", file_name, font_name);
  343.         if (count == EOF)
  344.         break;
  345.         if (count != 2) {
  346.             fclose(file);
  347.         return BadValue;
  348.         }
  349.         if (!FindFontFile (path, font_name, 0, FALSE, &matchTable) &&
  350.         (FindFileType (file_name) >= 0)) {
  351.         i = AddFileEntry(table, file_name, False);
  352.         if (i < 0) {
  353.             fclose(file);
  354.             return BadAlloc;
  355.         }
  356.         i = AddNameEntry(table, font_name, i);
  357.         if (i <= 0) {
  358.             fclose(file);
  359.             return (i ? BadAlloc : BadValue);
  360.         }
  361.         }
  362.     }
  363.     fclose(file);
  364.     }
  365.     else if (errno != ENOENT)
  366.     {
  367.     return BadValue;
  368.     }
  369.     status = ReadFontAlias(directory, FALSE, &table, path);
  370.     if (status != Success)
  371.     {
  372.     FreeFontTable(table);
  373.     return status;
  374.     }
  375.     if (!table)
  376.     return BadValue;
  377.     /*
  378.      * At this point, no more entries will be made in file table. This means
  379.      * that it will not be realloced and we can put pointers (rather than
  380.      * indices into the table.
  381.      */
  382.     for (i = 0; i < table->name.used; i++)
  383.     table->name.fn[i].u.ff = &table->file.ff[table->name.fn[i].u.index];
  384.  
  385.     *ptable = table;
  386.     return Success;
  387. }
  388.  
  389. /* 
  390.  * Make each of the file names an automatic alias for each of the files.
  391.  * This assumes that all file names are of the form <root>.<extension>.
  392.  */
  393.  
  394. static Bool
  395. AddFileNameAliases(table, path)
  396.     FontTable table;
  397.     FontPathPtr path;
  398. {
  399.     int i, typeIndex;
  400.     Boolean found;
  401.     FontTable    matchTable;
  402.  
  403.     char copy[MAXPATHLEN];
  404.  
  405.     for (i = 0; i < table->file.used; i++) {
  406.     if (table->file.ff[i].alias)
  407.         continue;
  408.     strcpy(copy, table->file.ff[i].name);
  409.     typeIndex = FindFileType(copy);
  410.     copy[strlen(copy) - strlen(fontFileReaders[typeIndex].extension)] = NUL;
  411.     CopyISOLatin1Lowered ((unsigned char *)copy, (unsigned char *)copy,
  412.                   strlen (copy));
  413.     (void)  FindNameInFontTable(table, copy, &found);
  414.     if (!found && !FindFontFile (path, copy, 0, FALSE, &matchTable)) {
  415.         if (AddNameEntry(table, copy, i) < 0)
  416.         return FALSE;
  417.     }
  418.     }
  419.     return TRUE;
  420. }
  421.  
  422. /*
  423.  * parse the font.aliases file.  Format is:
  424.  *
  425.  * alias font-name
  426.  *
  427.  * To imbed white-space in an alias name, enclose it like "font name" 
  428.  * in double quotes.  \ escapes and character, so
  429.  * "font name \"With Double Quotes\" \\ and \\ back-slashes"
  430.  * works just fine.
  431.  */
  432.  
  433. /*
  434.  * token types
  435.  */
  436.  
  437. static int    lexAlias (), lexc ();
  438.  
  439. # define NAME        0
  440. # define NEWLINE    1
  441. # define DONE        2
  442. # define EALLOC        3
  443.  
  444. static int
  445. ReadFontAlias(directory, isFile, ptable, path)
  446.     char      *directory;
  447.     Bool      isFile;
  448.     FontTable *ptable;
  449.     FontPathPtr path;
  450. {
  451.     char alias[MAXPATHLEN];
  452.     char font_name[MAXPATHLEN];
  453.     char alias_file[MAXPATHLEN];
  454.     char buf[BUFSIZ];
  455.     FILE *file;
  456.     int i;
  457.     FontTable matchTable;
  458.     FontTable table;
  459.     int    token;
  460.     Bool found;
  461.     char *lexToken;
  462.     int status = Success;
  463.  
  464.     table = *ptable;
  465.     strcpy(alias_file, directory);
  466.     if (!isFile)
  467.     {
  468.     if (directory[strlen(directory) - 1] != '/')
  469.         strcat(alias_file, "/");
  470.     strcat(alias_file, AliasFile);
  471.     }
  472.     file = fopen(alias_file, "r");
  473.     if (!file)
  474.     return ((errno == ENOENT) ? Success : BadValue);
  475.     setbuf (file, buf);
  476.     if (!table)
  477.     *ptable = table = MakeFontTable (directory, 10);
  478.     if (!table)
  479.     return BadAlloc;
  480.     while (status == Success) {
  481.     token = lexAlias (file, &lexToken);
  482.     switch (token) {
  483.     case NEWLINE:
  484.         break;
  485.     case DONE:
  486.         fclose (file);
  487.         return Success;
  488.     case EALLOC:
  489.         status = BadAlloc;
  490.         break;
  491.     case NAME:
  492.         strcpy (alias, lexToken);
  493.         token = lexAlias (file, &lexToken);
  494.         switch (token) {
  495.         case NEWLINE:
  496.         if (strcmp (alias, "FILE_NAMES_ALIASES"))
  497.             status = BadValue;
  498.         else if (!AddFileNameAliases (table, path))
  499.             status = BadAlloc;
  500.         break;
  501.         case DONE:
  502.         status = BadValue;
  503.         break;
  504.         case EALLOC:
  505.         status = BadAlloc;
  506.         break;
  507.         case NAME:
  508.         CopyISOLatin1Lowered ((unsigned char *)alias,
  509.                       (unsigned char *)alias,
  510.                       strlen (alias));
  511.         CopyISOLatin1Lowered ((unsigned char *)font_name,
  512.                       (unsigned char *)lexToken,
  513.                       strlen (lexToken));
  514.         (void) FindNameInFontTable (table, alias, &found);
  515.         if (!found &&
  516.             !FindFontFile (path, alias, 0, FALSE, &matchTable)) {
  517.             i = AddFileEntry(table, font_name, True);
  518.             if (i < 0) {
  519.             status = BadAlloc;
  520.             } else {
  521.             i = AddNameEntry(table, alias, i);
  522.             if (i <= 0)
  523.                 status = (i ? BadAlloc : BadValue);
  524.             }
  525.         }
  526.         break;
  527.         }
  528.     }
  529.     }
  530.     fclose(file);
  531.     return status;
  532. }
  533.  
  534. # define QUOTE        0
  535. # define WHITE        1
  536. # define NORMAL        2
  537. # define END        3
  538. # define NL        4
  539.  
  540. static int    charClass;
  541.  
  542. static int
  543. lexAlias (file, lexToken)
  544. FILE    *file;
  545. char    **lexToken;
  546. {
  547.     int        c;
  548.     char        *t;
  549.     enum state { Begin, Normal, Quoted } state;
  550.     int        count;
  551.  
  552.     static char    *tokenBuf = (char *)NULL;
  553.     static int    tokenSize = 0;
  554.  
  555.     t = tokenBuf;
  556.     count = 0;
  557.     state = Begin;
  558.     for (;;) {
  559.         if (count == tokenSize) {
  560.             int nsize;
  561.             char *nbuf;
  562.  
  563.             nsize = tokenSize ? (tokenSize << 1) : 64;
  564.             nbuf = (char *)xrealloc(tokenBuf, nsize);
  565.             if (!nbuf)
  566.             return EALLOC;
  567.             tokenBuf = nbuf;
  568.             tokenSize = nsize;
  569.             t = tokenBuf + count;
  570.         }
  571.         c = lexc (file);
  572.         switch (charClass) {
  573.         case QUOTE:
  574.             switch (state) {
  575.             case Begin:
  576.             case Normal:
  577.                 state = Quoted;
  578.                 break;
  579.             case Quoted:
  580.                 state = Normal;
  581.                 break;
  582.             }
  583.             break;
  584.         case WHITE:
  585.             switch (state) {
  586.             case Begin:
  587.                 continue;
  588.             case Normal:
  589.                 *t = '\0';
  590.                 *lexToken = tokenBuf;
  591.                 return NAME;
  592.             case Quoted:
  593.                 break;
  594.             }
  595.             /* fall through */
  596.         case NORMAL:
  597.             switch (state) {
  598.             case Begin:
  599.                 state = Normal;
  600.             }
  601.             *t++ = c;
  602.             ++count;
  603.             break;
  604.         case END:
  605.         case NL:
  606.             switch (state) {
  607.             case Begin:
  608.                 *lexToken = (char *)NULL;
  609.                 return charClass == END ? DONE : NEWLINE;
  610.             default:
  611.                 *t = '\0';
  612.                 *lexToken = tokenBuf;
  613.                 ungetc (c, file);
  614.                 return NAME;
  615.             }
  616.         }
  617.     }
  618. }
  619.  
  620. static int
  621. lexc (file)
  622. FILE    *file;
  623. {
  624.     int    c;
  625.     c = getc (file);
  626.     switch (c) {
  627.     case EOF:
  628.         charClass = END;
  629.         break;
  630.     case '\\':
  631.         c = getc (file);
  632.         if (c == EOF)
  633.             charClass = END;
  634.         else
  635.             charClass = NORMAL;
  636.         break;
  637.     case '"':
  638.         charClass = QUOTE;
  639.         break;
  640.     case ' ':
  641.     case '\t':
  642.         charClass = WHITE;
  643.         break;
  644.     case '\n':
  645.         charClass = NL;
  646.         break;
  647.     default:
  648.         charClass = NORMAL;
  649.         break;
  650.     }
  651.     return c;
  652. }
  653.  
  654. static Bool
  655. SearchDirectory(index, pat, fontList, limit)
  656.     int index;
  657.     char *pat;
  658.     FontPathPtr fontList;
  659.     unsigned limit;
  660. {
  661.     int i, res, len, head, tail;
  662.     FontTable table;
  663.  
  664.     if (!searchList)
  665.     return TRUE;
  666.     table = (FontTable)searchList->osPrivate[index];
  667.     i = SetupWildMatch(table, pat, (char *)NULL, &head, &tail, &len);
  668.     while (i < table->name.used)
  669.     {
  670.     res = Match(table->name.fn[i].name, pat, head, tail, len);
  671.     if (res > 0)
  672.     {
  673.         if (AddFontPathElement(fontList, table->name.fn[i].name,
  674.                    strlen(table->name.fn[i].name), False))
  675.         return FALSE;
  676.         if (fontList->npaths >= limit)
  677.         break;
  678.     }
  679.     else if (res < 0)
  680.         break;
  681.     i++;
  682.     }
  683.     return TRUE;
  684. }
  685.  
  686. /*******************************************************************
  687.  *  ExpandFontNamePattern
  688.  *
  689.  *    Returns a FontPathPtr with at most max-names, of names of fonts
  690.  *      matching
  691.  *    the pattern.  The pattern should use the ASCII encoding, and
  692.  *      upper/lower case does not matter.  In the pattern, the '?' character
  693.  *    (octal value 77) will match any single character, and the character '*'
  694.  *    (octal value 52) will match any number of characters.  The return
  695.  *    names are in lower case.
  696.  *
  697.  *      Used only by protocol request ListFonts & ListFontsWithInfo
  698.  *******************************************************************/
  699.  
  700. FontPathPtr
  701. ExpandFontNamePattern(lenpat, countedPattern, maxNames)
  702.     unsigned    lenpat;
  703.     char    *countedPattern;
  704.     unsigned    maxNames;
  705. {
  706.     char    *pattern;
  707.     int        i;
  708.     FontPathPtr    fpr;
  709.  
  710.     if (!searchList)
  711.     return (FontPathPtr)NULL;
  712.     /* random number, this is a guess, but it hardly matters. */
  713.     fpr = MakeFontPathRecord ((unsigned) 100);
  714.     if (!fpr)
  715.     return (FontPathPtr)NULL;
  716.     pattern = (char *)ALLOCATE_LOCAL (lenpat + 1);
  717.     if (!pattern)
  718.     {
  719.     FreeFontRecord(fpr);
  720.     return (FontPathPtr)NULL;
  721.     }
  722.     /*
  723.      * make a pattern which is guaranteed NULL-terminated
  724.      */
  725.     CopyISOLatin1Lowered((unsigned char *)pattern,
  726.              (unsigned char *)countedPattern,
  727.              (int) lenpat);
  728.  
  729.     for ( i=0; i<searchList->npaths; i++)
  730.     {
  731.     if (!SearchDirectory(i, pattern, fpr, maxNames))
  732.     {
  733.         FreeFontRecord(fpr);
  734.         return (FontPathPtr)NULL;
  735.     }
  736.     if (fpr->npaths >= maxNames)
  737.         break;
  738.     }
  739.     DEALLOCATE_LOCAL(pattern);
  740.     return fpr;
  741. }
  742.  
  743. /*
  744.  * OS interface to reading font files. This is not called by the dix routines
  745.  * but rather by any of the pseudo-os-independent font internalization
  746.  * routines.
  747.  */
  748.  
  749. int
  750. FontFileRead(buf, itemsize, nitems, fid)
  751.     char    *buf;
  752.     unsigned    itemsize;
  753.     unsigned    nitems;
  754.     FID        fid;
  755. {
  756.     return fread( buf, (int) itemsize, (int) nitems, (FILE *)fid);
  757. }
  758.  
  759. int
  760. FontFileSkip(bytes, fid)
  761.     unsigned    bytes;
  762.     FID        fid;
  763. {
  764.     struct stat    stats;
  765.     int c;
  766.  
  767.     fstat(fileno((FILE *)fid), &stats);
  768.     if ((stats.st_mode & S_IFMT) == S_IFREG)
  769.     c = fseek((FILE *) fid, (long) bytes, 1);
  770.     else
  771.     while (bytes-- && ((c = getc((FILE *)fid)) != EOF))
  772.         ;
  773.     return c;
  774. }
  775.  
  776. /*
  777.  * When a font is unloaded (destroyed) it is necessary to remove the pointer
  778.  * in the font table since it is no longer valid. This means that the
  779.  * "obvious" technique of putting the FontPtr into the table when an aliased
  780.  * font is loaded would mean that the table would have to be searched for
  781.  * any matching entry. To avoid scanning all the tables when a font is FontPtr
  782.  * destroyed, the Font has a back pointer to the FontFile (in the table) where
  783.  * it was entered.
  784.  *
  785.  * So that aliases will not also keep a copy of the FontPtr in their FontTable
  786.  * entries, a pointer to the "resolved" FontTable is actually kept and the
  787.  * indirection is taken.
  788.  *
  789.  * A slight non-conformance to the protocol is possible here. If any
  790.  * FontTable is for a file that does not load (i.e. was changed since the
  791.  * font.dirs was created), then that font name will not work even though it
  792.  * should because of wild carding or the use of a search path. The moral is
  793.  * is that the font.dirs should be correct.
  794.  *
  795.  * To prevent circular aliases from crashing the server (due to the recursive
  796.  * nature of FindFontFile) a limit of MAX_LINKS is put on the length of a
  797.  * chain that will be followed.
  798.  */
  799.  
  800. #define MAX_LINKS 20
  801.  
  802. static FontFile 
  803. FindFontFile(path, fontname, depth, followAliases, table)
  804.     FontPathPtr path;
  805.     char *    fontname;
  806.     int        depth;
  807.     Bool    followAliases;    
  808.     FontTable    *table;     /* returned */
  809. {
  810.     int     nameIndex, i;
  811.     Bool found;
  812.     FontFile ff, resolved;
  813.  
  814.     if (!path || (depth >= MAX_LINKS))
  815.     return NullFontFile;
  816.     for (i = 0; i < path->npaths; i++)
  817.     {
  818.     *table = (FontTable) path->osPrivate[i];
  819.     nameIndex = FindNameInFontTable (*table, fontname, &found);
  820.     if (!found)
  821.         continue;
  822.     ff = (*table)->name.fn[nameIndex].u.ff;
  823.     if (!ff->alias || !followAliases)
  824.         return ff;
  825.     if (resolved = FindFontFile (path, ff->name, depth + 1, TRUE, table))
  826.     {
  827.         ff->private = (Opaque) resolved;
  828.         return resolved;
  829.     }
  830.     }
  831.     return NullFontFile;
  832. }
  833.  
  834. #if defined(SYSV) && !defined(hpux)        /* hpux does have vfork */
  835. #define vfork() fork()
  836. #endif
  837.  
  838. #ifdef apollo               /* Domain/OS has vfork but it breaks the graphics layer */
  839. #define vfork() fork()
  840. #endif
  841.  
  842. static int
  843. FontFilter(fp, filter)
  844.     FILE *fp;
  845.     char **filter;
  846. {
  847.     int pfd[2];
  848.     int pid;
  849.  
  850.     if (pipe(pfd) < 0) {
  851.     fclose(fp);
  852.     return (-1);
  853.     }
  854.     switch(pid = vfork()) {
  855.     case 0:
  856.     dup2(fileno(fp), 0);
  857.     close(fileno(fp));
  858.     dup2(pfd[1], 1);
  859.     close(pfd[0]);
  860.     close(pfd[1]);
  861.     execvp(filter[0], filter);
  862.     _exit(127);
  863.     case -1:
  864.     close(pfd[0]);
  865.     close(pfd[1]);
  866.     fclose(fp);
  867.     return(-1);
  868.     default:
  869.     dup2(pfd[0], fileno(fp));
  870.     close(pfd[0]);
  871.     close(pfd[1]);
  872.     return(pid);
  873.     }    
  874. }
  875.  
  876. static FILE *
  877. OpenFontFile(table, name, typeIndex, pid)
  878.     FontTable table;
  879.     char     *name;
  880.     int         *typeIndex;
  881.     int      *pid;
  882. {
  883.     char    pathName[MAXPATHLEN];
  884.     FILE   *fp;
  885.     char **filter;
  886.  
  887.     strcpy (pathName, table->directory);
  888.     strcat (pathName, name);
  889.     if ((fp = fopen (pathName, "r")) == (FILE *)NULL)
  890.     return fp;
  891.     *pid = 0;
  892.     *typeIndex = FindFileType (name);
  893.     filter = fontFileReaders[*typeIndex].filter;
  894.     if (filter) {
  895.     *pid = FontFilter(fp, filter);
  896.     if (*pid < 0)
  897.         return (FILE *)NULL;
  898.     }
  899.     return fp;
  900. }
  901.  
  902. static void
  903. CloseFontFile(fp, pid)
  904.     FILE *fp;
  905.     int pid;
  906. {
  907.     int child;
  908.  
  909.     fclose (fp);
  910.     if (pid >= 0)
  911.        do { child = wait(0); } while (child != pid && child != -1);
  912. }
  913.  
  914. FontPtr 
  915. FontFileLoad(fontname, length)
  916.     unsigned    length;
  917.     char *    fontname;
  918. {
  919.     FontPtr    font;
  920.     char    fName[MAXPATHLEN];
  921.     char    buf[BUFSIZ];
  922.     FILE    * fp;
  923.     FontTable    table;
  924.     FontFile    ff;
  925.     int        typeIndex;
  926.     int        cookie;
  927.  
  928.     CopyISOLatin1Lowered((unsigned char *)fName, (unsigned char *)fontname,
  929.              (int) length);
  930.     ff = FindFontFile (searchList, fName, 1, TRUE, &table);
  931.     if (!ff)
  932.     return NullFont;
  933.     if (ff->private != NULL)
  934.     return (FontPtr) ff->private;    /* already loaded */
  935.     if ((fp = OpenFontFile(table, ff->name, &typeIndex, &cookie)) == NULL)
  936.     return NullFont;
  937.     setbuf (fp, buf);
  938.     font = (fontFileReaders[typeIndex].loadFont) (fp);
  939.     CloseFontFile(fp, cookie);
  940.     if (font == NullFont)
  941.     return NullFont;
  942.     ff->private = (Opaque) font;
  943.     font->refcnt = 0;
  944.     font->fileType = typeIndex;
  945.     font->osPrivate = (pointer) ff;
  946.     return font;
  947. }
  948.  
  949. /*
  950.  * This either returns an existing font, or if that can't be found,
  951.  * then fills in the FontInfo and FontProp by reading from the disk.
  952.  */
  953.  
  954. Bool
  955. FontFilePropLoad(fontname, length, font, fi, props)
  956.     char    *fontname;
  957.     unsigned int length;
  958.     FontInfoPtr fi;
  959.     DIXFontPropPtr *props;    /* return */
  960.     FontPtr    *font;        /* return */
  961. {
  962.     char    fName[MAXPATHLEN];
  963.     FILE *    fp;
  964.     FontTable    table;
  965.     FontFile    ff;
  966.     Bool    found;
  967.     int        typeIndex;
  968.     char    buf[BUFSIZ];
  969.     int        cookie;
  970.  
  971.     CopyISOLatin1Lowered((unsigned char *)fName, (unsigned char *)fontname,
  972.              (int) length);
  973.     ff = FindFontFile (searchList, fName, 1, TRUE, &table);
  974.     if (!ff)
  975.     return FALSE;
  976.     if (ff->private != NULL) {
  977.     *font = (FontPtr) ff->private;
  978.     return TRUE;
  979.     }
  980.     *font = NullFont;
  981.     if ((fp = OpenFontFile(table, ff->name, &typeIndex, &cookie)) == NULL)
  982.     return FALSE;
  983.     setbuf (fp, buf);
  984.     found = (*fontFileReaders[typeIndex].loadProperties) (fp, fi, props);
  985.     CloseFontFile(fp, cookie);
  986.     return found;
  987. }
  988.  
  989. void FontUnload(font)
  990.     FontPtr font;
  991. {
  992.     FontFile ff;
  993.     if ((ff = (FontFile)font->osPrivate) != NULL)
  994.     ff->private = NULL;
  995.     (*fontFileReaders[font->fileType].freeFont)(font);
  996. }
  997. @
  998.